package com.cloudfun.campusshare.configuration.jpa.restriction;


import com.cloudfun.campusshare.configuration.jpa.specification.SpecificationModel;
import com.cloudfun.campusshare.configuration.jpa.specification.SpecificationUtil;
import com.cloudfun.campusshare.configuration.jpa.util.MatchValue;
import com.cloudfun.campusshare.configuration.jpa.util.PredicateBuilder;
import com.cloudfun.campusshare.configuration.jpa.util.PropertyFilter;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;

/**
 * @author 王溪源
 * @ClassName: PredicateSingleValueSupport
 * @Description: TODO
 **/
public abstract class PredicateSingleValueSupport implements PredicateBuilder {
    private String orValueSeparartor = "|";

    private String andValueSeparator = ",";

    public PredicateSingleValueSupport() {
    }

    @Override
    public Predicate build(PropertyFilter filter, SpecificationModel model) {
        String matchValue = filter.getMatchValue ();
        Class<?> propertyType = filter.getPropertyType ();
        MatchValue matchValueModel = getMatchValue (matchValue, propertyType);
        Predicate predicate;
        if (matchValueModel.isHasOrOperate ()) {
            predicate = model.getBuilder ().disjunction ();
        } else {
            predicate = model.getBuilder ().conjunction ();
        }
        if (filter.hasMultiplePropertyNames ()) {
            Predicate orPredicate = model.getBuilder ().disjunction ();
            for (String propertyName : filter.getPropertyNames ()) {
                for (Object value : matchValueModel.getValues ()) {
                    orPredicate.getExpressions ().add (build (propertyName, value, model));
                }
            }
            predicate = orPredicate;
        } else {
            for (Object value : matchValueModel.getValues ()) {
                predicate.getExpressions ().add (build (filter.getSinglePropertyName (), value, model));
            }
        }
        return predicate;
    }

    @Override
    public Predicate build(String singlePropertyName, Object value, SpecificationModel model) {
        return build (SpecificationUtil.getPath (singlePropertyName, model.getRoot ()), value, model.getBuilder ());
    }

    public abstract Predicate build(Path<?> path, Object value, CriteriaBuilder builder);

    public MatchValue getMatchValue(String matchValue, Class<?> propertyType) {
        return MatchValue.createMatchValueModel (matchValue, propertyType, andValueSeparator, orValueSeparartor);
    }

    public String getAndValueSeparator() {
        return andValueSeparator;
    }

    public void setAndValueSeparator(String andValueSeparator) {
        this.andValueSeparator = andValueSeparator;
    }
}
